package com.rzn.reading;

import com.github.dozermapper.core.DozerBeanMapperBuilder;
import com.github.dozermapper.core.Mapper;
import com.rzn.reading.utils.StringUtil;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.BiFunction;


@Component
public class BeanMapper {

    private static final Mapper mapper = DozerBeanMapperBuilder.create().build();

    public static Mapper getMapper() {
        return mapper;
    }


    public static <T, S> T map(S source, Class<T> destinationClass) {
        if (null == source) {
            return null;
        }
        return mapper.map(source, destinationClass);
    }

    public static <T> List<T> mapList(Collection<?> sourceList, Class<T> destinationClass) {
        if (null == sourceList) {
            return null;
        }
        List<T> destinationList = new ArrayList<>();
        for (Object sourceObject : sourceList) {
            destinationList.add(map(sourceObject, destinationClass));
        }
        return destinationList;
    }

    public static <T, S> List<T> mapList(Collection<S> sourceList, Class<T> destinationClass, BiFunction<S, T, T> postHandler) {
        if (null == sourceList) {
            return null;
        }
        List<T> destinationList = new ArrayList<>();
        for (S sourceObject : sourceList) {
            T tmp = map(sourceObject, destinationClass);
            destinationList.add(postHandler.apply(sourceObject, tmp));
        }
        return destinationList;
    }

    /**
     * 基于Dozer将对象A的值拷贝到对象B中.
     */
    public static void copy(Object source, Object destinationObject) {
        mapper.map(source, destinationObject);
    }

    public static <S, T> void mapBean(S source, T target) {
        Class<?> entityClass = source.getClass();
        Class<?> targetClass = target.getClass();
        Field[] entityFields = entityClass.getDeclaredFields();
        for (Field entityField : entityFields) {
            String fieldName = entityField.getName();
            fieldName = StringUtil.toTitle(fieldName);

            try {
                Method entityMethod = entityClass.getMethod("get" + fieldName);
                Method targetMethod = targetClass.getMethod("set" + fieldName, entityField.getType());
                Object value = entityMethod.invoke(source);
                targetMethod.invoke(target, value);
            } catch (NoSuchMethodException e) {
                System.out.println("方法" + "'" + e.getMessage() + "'" + "没找到");
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }

    public static <S, T> List<T> mapBeanList(List<S> sourceList, Class<T> targetClass) {
        List<T> targetList = new ArrayList<>();
        for (S source : sourceList) {
            try {
                T target = targetClass.newInstance();
                mapBean(source, target);
                targetList.add(target);
            } catch (IllegalAccessException | InstantiationException e) {
                e.printStackTrace();
            }
        }
        return targetList;
    }
}
